<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta http-equiv="cache-control" content="no-cache">
<title>Genivia - The Apache module for gSOAP</title>
<link href="genivia_tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css">
<link href="genivia_content.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="top">
 <div id="titlearea">
  <table height="72px" width="100%" cellspacing="0" cellpadding="0">
   <tbody>
    <tr>
     <td width="10%">&nbsp;</td>
     <td width="175px"><a href="https://www.genivia.com"><img alt="Genivia" src="GeniviaLogo2_trans_noslogan.png"/></a></td>
     <td class="tab_home"><a href="https://www.genivia.com">Home</a></td>
     <td class="tab_home"><a href="https://www.genivia.com/docs.html">Documentation</a></td>
     <td>
      <div style="float: right; font-size: 18px; font-weight: bold;">The Apache module for gSOAP</div>
      <br>
      <div style="float: right; font-size: 10px;">updated Thu Jun 24 2021 by Robert van Engelen</div>
     </td>
     <td width="10%">&nbsp;</td>
    </tr>
   </tbody>
  </table>
 </div>
<!-- Generated by Doxygen 1.8.11 -->
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li class="current"><a href="index.html"><span>Main&#160;Page</span></a></li>
      <li><a href="annotated.html"><span>Classes</span></a></li>
      <li><a href="files.html"><span>Files</span></a></li>
    </ul>
  </div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">The Apache module for gSOAP </div>  </div>
</div><!--header-->
<div class="contents">
<div class="toc"><h3>Table of Contents</h3>
<ul><li class="level1"><a href="#overview">Overview                                                             </a></li>
<li class="level1"><a href="#install">Installation                                                          </a></li>
<li class="level1"><a href="#deploy">Deploying C services with the Apache module                            </a></li>
<li class="level1"><a href="#plugins">Initialization and plugins                                            </a></li>
<li class="level1"><a href="#rest">REST services                                                           </a></li>
<li class="level1"><a href="#libraries">Dynamic libraries                                                   </a></li>
<li class="level1"><a href="#classes">Building C++ services from service classes                            </a></li>
<li class="level1"><a href="#debug">Troubleshooting                                                         </a></li>
<li class="level1"><a href="#limitations">Limitations                                                       </a></li>
<li class="level1"><a href="#license">License                                                               </a></li>
<li class="level1"><a href="#references">Further reading                                                    </a></li>
</ul>
</div>
<div class="textblock"><p>By Christian Aberger, Mick Wall, Robert van Engelen, David Viner, Ryan Troll, and La Cam Chung.</p>
<h1><a class="anchor" id="overview"></a>
Overview                                                             </h1>
<p>SOAP/XML and REST Web services can be easily created and deployed as gSOAP standalone services or installed as (Fast)CGI applications. In addition, the <code>mod_gsoap</code> Apache module offers the ability to run gSOAP services directly inside the Apache HTTP server. The <code>mod_gsoap</code> Apache module supports the deployment of multiple gSOAP services that can run together with the usual services on Apache. This approach offers a production-quality Web services deployment scenario.</p>
<p>The <code>mod_gsoap</code> Apache module is designed to keep things simple so that existing gSOAP services can be recompiled for Apache HTTP server deployment without modification of the source code. The Apache <code>apxs</code> command compiles your gSOAP service code and installs it with <code>mod_gsoap</code>. Add your new service to Apache <code>httpd.conf</code> and presto!</p>
<p>The original Apache module for gSOAP home page is at <a href="http://mod-gsoap.sourceforge.net">http://mod-gsoap.sourceforge.net</a>. Newer versions are included in the gSOAP distribution package in the <code>gsoap/mod_gsoap/mod_gsoap-0.9</code> directory.</p>
<p>Apache modules for gSOAP are provided for both Apache 1.3 and 2.x. In the following we will discuss the Apache module for Apache 2.x.</p>
<h1><a class="anchor" id="install"></a>
Installation                                                          </h1>
<p>First download the <a href="https://httpd.apache.org">Apache httpd</a> source code and install the httpd server in a new directory, say <code>apachegsoap</code>: </p><pre class="fragment">mkdir apachegsoap
cd apachegsoap
tar -xjf httpd-2.4.48.tar.bz2
cd httpd-2.4.48
./configure --prefix=`pwd`/.. --with-mpm=worker --enable-mods-shared=most
make -j4
make install
</pre><p>If configure fails with "error: APR not found" or "error: APR-util not found", download and install the <a href="http://apr.apache.org">Apache Portable Runtime</a> (APR).</p>
<p>To use the Apache extension mechanism, your platform has to support the DSO feature and your Apache <code>httpd</code> binary has to be built with the <code>mod_so</code> module. The <code>apxs</code> tool automatically complains if this is not the case. You can check this yourself by manually running the <code>httpd -l</code> command (installed locally in <code>apachegsoap/bin</code> with the instructions above): </p><pre class="fragment">cd apachegsoap
bin/httpd -l
</pre><p>The module <code>mod_so.c</code> should be on the displayed list of modules.</p>
<p>Next, we will build and install <code>mod_gsoap</code> for Apache 2.x and up. The source code files are located under <code>gsoap/mod_gsoap/mod_gsoap-0.9/apache_20</code> and include <code><a class="el" href="apache__gsoap_8h.html">apache_gsoap.h</a></code>, <code><a class="el" href="mod__gsoap_8c.html">mod_gsoap.c</a></code>, and a Visual Studio project file <code>mod_gsoap.vcproj</code>.</p>
<p>To compile <code>mod_gsoap</code>, execute: </p><pre class="fragment">cd /path/to/gsoap/installation/gsoap/mod_gsoap/mod_gsoap-0.9/apache_20
ln -s ../../../stdsoap2.h .
sudo $HOME/apachegsoap/bin/apxs -a -i -DWITH_GZIP -lz -c mod_gsoap.c
</pre><p>Invoking <code>apxs</code> with <code>-DWITH_GZIP -lz</code> enables decompression in <code>mod_gsoap</code> with libz (<code>-lz</code>), which is not required, but useful and recommended.</p>
<p>Root permissions are required, so we used <code>sudo apxs</code> here.</p>
<p>The <code>apxs</code> command should be on your path or located in <code>apachegsoap/bin</code> where we installed httpd. Make sure to use <code>$HOME/apachegsoap/bin/apxs</code> if multiple httpd versions are installed.</p>
<p>If a specific C compiler is required, say <code>cc</code>, then try <code>apxs -S CC=cc ...</code>.</p>
<h1><a class="anchor" id="deploy"></a>
Deploying C services with the Apache module                            </h1>
<p>After building <code>mod_gsoap</code> we are ready to deploy gSOAP services written in C with the Apache module.</p>
<p>The gSOAP package contains a calculator example. We will use this example to walk you through the creation and deployment of an Apache module gSOAP service.</p>
<p>First, copy the calculator example: </p><pre class="fragment">cd apachegsoap
cp /path/to/gsoap/installation/gsoap/samples/calc/* .
cp /path/to/gsoap/installation/gsoap/stdsoap2.* .
cp /path/to/gsoap/installation/gsoap/mod_gsoap/mod_gsoap-0.9/apache_20/apache_gsoap.h .
</pre><p>Next, edit <code>calcserver.c</code> by removing <code>main()</code> and replace it with <code><a class="el" href="apache__gsoap_8h.html#a044247a029c4997b5b22bba46d3ef233">IMPLEMENT_GSOAP_SERVER()</a></code> as follows:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="apache__gsoap_8h.html">apache_gsoap.h</a>&quot;</span></div><div class="line"><a class="code" href="apache__gsoap_8h.html#a044247a029c4997b5b22bba46d3ef233">IMPLEMENT_GSOAP_SERVER</a>() <span class="comment">/* replaces main() { ... } */</span></div></div><!-- fragment --><p>To initialize the engine context with flags and/or plugins, see <a class="el" href="index.html#plugins">Initialization and plugins </a>.</p>
<p>Then compile and build the service: </p><pre class="fragment">soapcpp2 -c -SL -wx calc.h
sudo $HOME/apachegsoap/bin/apxs -a -c calcserver.c soapC.c soapServer.c stdsoap2.c
chmod 755 .libs/calcserver.so
</pre><p>Again, the <code>apxs</code> command should be on your path or located in <code>apachegsoap/bin</code> where we installed httpd. Make sure to use <code>$HOME/apachegsoap/bin/apxs</code> as shown above if multiple httpd versions are installed.</p>
<p>This creates <code>.libs/calcserver.so</code> service module that is universally readable. Also make sure that <code>.libs/calcserver.so</code> is readable through the entire path, that is through <code>/home/username/apachegsoap/.libs</code> where <code>username</code> is your user account name.</p>
<p>If you have installed source files in other directories, then you will need to add appropriate <code>-I</code> and <code>-L</code> options with the <code>apxs</code> command shown above.</p>
<p>To deploy the service, we will need to add our module with its properties to <code>httpd.conf</code> (for example we can add it at the end): </p><pre class="fragment">&lt;IfModule mod_gsoap.c&gt;
 &lt;Location /soap&gt;
  SetHandler gsoap_handler
  SOAPLibrary /home/username/apachegsoap/.libs/calcserver.so
  Order allow,deny
  Allow from all
 &lt;/Location&gt;
&lt;/IfModule&gt;
</pre><p>The <code>httpd.conf</code> file is usually found under <code>/private/etc/apache2/httpd.conf</code>. However, since we use a locally installed Apache <code>httpd</code> server that searches the <code>/home/username/apachegsoap</code> path, you will find <code>httpd.conf</code> in <code>/home/username/apachegsoap/conf</code>.</p>
<p>The <code>Location</code> property sets part of the URL of the service, which in this case will be <code><a href="http://localhost/soap">http://localhost/soap</a></code> or if you set a port that is different than the standard HTTP port 80, say 9080, the full URL is <code><a href="http://localhost:9080/soap">http://localhost:9080/soap</a></code>. To change the port from 80 to 9080, edit <code>httpd.conf</code> and change <code>Listen</code>: </p><pre class="fragment">Listen 9080
</pre><p>To start the service: </p><pre class="fragment">cd apachegsoap
bin/apachectl start
</pre><p>Point your browser to <code><a href="http://localhost:9080">http://localhost:9080</a></code> and the page should show the message "It works!".</p>
<p>To stop the server: </p><pre class="fragment">bin/apachectl stop
</pre><p>To use the service by client applications, direct the endpoint URL of clients to "http://localhost:9080/soap", for example in the <code>calcclient.c</code> code that came with the gSOAP example:</p>
<div class="fragment"><div class="line"><span class="keyword">const</span> <span class="keywordtype">char</span> server[] = <span class="stringliteral">&quot;http://localhost:9080/soap&quot;</span>;</div></div><!-- fragment --><p>Then we build the client: </p><pre class="fragment">soapcpp2 -c -CL -wx calc.h
cc -o calcclient calcclient.c soapC.c soapClient.c stdsoap2.c
</pre><p>and run it to send a request to perform a computation within the Apache server and to receive the response from the server, which is displayed: </p><pre class="fragment">./calcclient add 2 3
result = 5
</pre><p>To let clients access the WSDL of a service, you can use the query <code>?wsdl</code> as part of the URL such as <code><a href="http://localhost:9080/soap?wsdl">http://localhost:9080/soap?wsdl</a></code> to pull the file WSDL file from the current location of the service, e.g. <code>.libs/calcservice.wsdl</code> where our example <code>calcservice.so</code> lives. Copy the <code>calc.wsdl</code> file to <code>.libs/calcservice.wsdl</code> to make it available to the Apache server.</p>
<p>Deployment of multiple modules is possible since gSOAP 2.8.71, by specifying multiple <code>&lt;Location&gt;</code> entries in <code>&lt;IfModule <a class="el" href="mod__gsoap_8c.html">mod_gsoap.c</a>&gt;</code> in <code>httpd.conf</code>, one for each service. The change in gSOAP 2.8.71 modified function <code><a class="el" href="mod__gsoap_8c.html#a92fdc1d0e66a6382210db6e843e69f73">SoapSharedLibrary_load</a></code> in <code><a class="el" href="mod__gsoap_8c.html">mod_gsoap.c</a></code> as follows to resolve linking symbols locally:</p>
<div class="fragment"><div class="line"><span class="keyword">const</span> <span class="keywordtype">int</span> nFlags = RTLD_LAZY | RTLD_LOCAL; <span class="comment">// was RTLD_LAZY | RTLD_GLOBAL</span></div></div><!-- fragment --><p>Alternatively, if one module links against equally-named symbols coming from another module, then it is recommended to pass a version info file to the linker, instructing it to make all symbols local, except for the Apache module table instance. The version file (e.g. <code>myapachegsoap.ver</code>) looks something like this: </p><pre class="fragment">VERS_1.0 {
  global:
    myapachegsoap_module;
  local:
    *;
};
</pre><p>This file is then passed to the linker with option <code>-Wl,myapachegsoapv.ver</code>.</p>
<h1><a class="anchor" id="plugins"></a>
Initialization and plugins                                            </h1>
<p>By replacing <code>main()</code> with <code><a class="el" href="apache__gsoap_8h.html#a044247a029c4997b5b22bba46d3ef233">IMPLEMENT_GSOAP_SERVER()</a></code>, several functions are implemented that are used by the Apache module for gSOAP. These functions include <code><a class="el" href="apache__gsoap_8h.html#a09db8c18a5744c942c93ac87876cbff1">apache_default_soap_init()</a></code> to initialize a newly constructed context.</p>
<p>With gSOAP 2.8.54 and greater we can add our own initialization function to initialize the context. By doing so we can set context flags and register plugins. To define our own initialization function we use <code><a class="el" href="apache__gsoap_8h.html#aa9f6f697cc5fd4ab9e8692c3a97e4a74">IMPLEMENT_GSOAP_SERVER_INIT(init_func)</a></code> instead of <code><a class="el" href="apache__gsoap_8h.html#a044247a029c4997b5b22bba46d3ef233">IMPLEMENT_GSOAP_SERVER()</a></code>. For example, to enable XML indentation, MTOM attachments and message logging with the logging plugin:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &quot;plugin/logging.h&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="apache__gsoap_8h.html">apache_gsoap.h</a>&quot;</span></div><div class="line"><span class="keywordtype">void</span> mod_gsoap_init(<span class="keyword">struct</span> soap *soap, request_rec *r)</div><div class="line">{</div><div class="line">  <span class="keyword">static</span> FILE *fdi = NULL, *fdo = NULL;</div><div class="line">  <span class="keywordflow">if</span> (fdi == NULL)</div><div class="line">    fdi = fopen(<span class="stringliteral">&quot;/tmp/INBOUNDAUDIT.log&quot;</span>, <span class="stringliteral">&quot;a&quot;</span>);</div><div class="line">  <span class="keywordflow">if</span> (fdo == NULL)</div><div class="line">    fdo = fopen(<span class="stringliteral">&quot;/tmp/OUTBOUNDAUDIT.log&quot;</span>, <span class="stringliteral">&quot;a&quot;</span>);</div><div class="line">  soap_set_mode(soap, SOAP_XML_INDENT | SOAP_ENC_MTOM);</div><div class="line">  soap_register_plugin(soap, logging);</div><div class="line">  soap_set_logging_inbound(soap, fdi);</div><div class="line">  soap_set_logging_outbound(soap, fdo);</div><div class="line">}</div><div class="line"><a class="code" href="apache__gsoap_8h.html#aa9f6f697cc5fd4ab9e8692c3a97e4a74">IMPLEMENT_GSOAP_SERVER_INIT</a>(mod_gsoap_init) <span class="comment">/* replaces main() { ... } */</span></div></div><!-- fragment --><p>The <code>request_rec</code> type is an Apache structure that contains information for the module to process HTTP requests and respond accordingly. For details on this structure, please consult the Apache documentation.</p>
<p>The <code>soap_set_mode(soap, SOAP_XML_INDENT | SOAP_ENC_MTOM)</code> sets XML indentation in outbound XML messages and enables MTOM attachments.</p>
<p>The <code>soap_register_plugin(soap, logging)</code> and the following calls save the audit logs of inbound and outbound messages (note that messages are not continually flushed to the log files by the logging plugin, meaning the logs may appear incomplete until you stop httpd to close these files). The gsoap/plugin/logging.h and logging.c files are located in the gSOAP source code tree. Add logging.c to the apxs command to compile the logging plugin source code file.</p>
<p>Multiple plugin registrations can be performed as needed. The following plugins have been verified to work with the <code>mod_gsoap</code> Apache module:</p>
<ul>
<li>logging plugin to log messages</li>
<li>httpget plugin to support HTTP GET</li>
<li>httppost plugin to support HTTP PUT, PATCH, and DELETE</li>
<li>wsaapi (WSA) plugin for WS-Addressing, requires plugin registry with <code>SOAP_WSA_NEW_TRANSFER</code></li>
<li>wsseapi (WSSE) plugin for WS-Security</li>
<li>wstapi (WST) plugin for WS-Trust</li>
</ul>
<dl class="section note"><dt>Note</dt><dd>the wsaapi plugin should be registered with <code>soap_register_plugin_arg(soap, http_wsa, SOAP_WSA_NEW_TRANSFER)</code> to allow connection relays and data transfers to reply and error servers.</dd></dl>
<dl class="section warning"><dt>Warning</dt><dd>Do not use any of the <code>SOAP_IO</code> flags to initialize or set the context, such as <code>SOAP_IO_KEEPALIVE</code> and <code>SOAP_IO_CHUNK</code>. HTTP chunking is handled automatically and the Apache server manages its connections.</dd></dl>
<h1><a class="anchor" id="rest"></a>
REST services                                                           </h1>
<p>An example use of the httpget and httppost plugins (see previous section) to support HTTP GET and POST of JSON REST requests:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &quot;json.h&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;plugin/httpget.h&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;plugin/httppost.h&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="apache__gsoap_8h.html">apache_gsoap.h</a>&quot;</span></div><div class="line"><span class="keywordtype">void</span> mod_gsoap_init(<span class="keyword">struct</span> soap *soap, request_rec *r)</div><div class="line">{</div><div class="line">  <span class="keyword">static</span> <span class="keyword">struct </span>http_post_handlers handlers[] = {</div><div class="line">    { <span class="stringliteral">&quot;application/json&quot;</span>, json_post_handler },</div><div class="line">    { NULL }</div><div class="line">  };</div><div class="line">  soap_register_plugin_arg(soap, http_get, http_get_handler);</div><div class="line">  soap_register_plugin_arg(soap, http_post, handlers);</div><div class="line">}</div><div class="line"><a class="code" href="apache__gsoap_8h.html#aa9f6f697cc5fd4ab9e8692c3a97e4a74">IMPLEMENT_GSOAP_SERVER_INIT</a>(mod_gsoap_init) <span class="comment">/* replaces main() { ... } */</span></div></div><!-- fragment --><p>HTTP POST with Content-Type <code>application/json</code> is sent to the <code>http_post_handler</code>, for example a currentTime server (this is based on gsoap/samples/xml-rpc-json/json-currentTimeServer.c):</p>
<div class="fragment"><div class="line"><span class="keywordtype">int</span> json_post_handler(<span class="keyword">struct</span> soap *ctx)</div><div class="line">{</div><div class="line">  <span class="comment">/* receive JSON request */</span></div><div class="line">  <span class="keyword">struct </span>value request;</div><div class="line">  <span class="keywordflow">if</span> (soap_begin_recv(ctx)</div><div class="line">   || json_recv(ctx, &amp;request)</div><div class="line">   || soap_end_recv(ctx))</div><div class="line">  {</div><div class="line">    json_send_fault(ctx);</div><div class="line">  }</div><div class="line">  <span class="keywordflow">else</span></div><div class="line">  {</div><div class="line">    <span class="keywordflow">if</span> (is_string(&amp;request) &amp;&amp; !strcmp(*string_of(&amp;request), <span class="stringliteral">&quot;getCurrentTime&quot;</span>))</div><div class="line">    {</div><div class="line">      <span class="keyword">struct </span>value *response = new_value(ctx);</div><div class="line">      *dateTime_of(response) = soap_dateTime2s(ctx, time(0));</div><div class="line">      ctx-&gt;http_content = <span class="stringliteral">&quot;application/json; charset=utf-8&quot;</span>;</div><div class="line">      <span class="keywordflow">if</span> (soap_response(ctx, SOAP_FILE)</div><div class="line">       || json_send(ctx, response)</div><div class="line">       || soap_end_send(ctx))</div><div class="line">        <span class="keywordflow">return</span> soap-&gt;error;</div><div class="line">    }</div><div class="line">    <span class="keywordflow">else</span></div><div class="line">    {</div><div class="line">      <span class="comment">/* JSON error as per Google JSON Style Guide */</span></div><div class="line">      json_send_error(ctx, 400, <span class="stringliteral">&quot;Wrong method&quot;</span>, *string_of(&amp;request));</div><div class="line">    }</div><div class="line">  }</div><div class="line">  <span class="keywordflow">return</span> ctx-&gt;error;</div><div class="line">}</div></div><!-- fragment --><p>Note that <code>soap_response(soap, SOAP_FILE)</code> produces the HTTP 200 OK response header with the HTTP Content-Type specified by <code>soap-&gt;http_content</code>. To return a specific HTTP status code, return the status code from the handler: a handler may return <code>SOAP_OK</code> or an HTTP status error code to indicate success or failure, respecively. To decline a request return <code>DECLINED</code> without producing a response message.</p>
<p>A <code>soap_closesock()</code> call is typically used with stand-alone servers, but is not needed to "close" the connection in the Apache module, but harmless when called, even when called more than once.</p>
<p>If <code>soap_serve()</code> is not generated by soappcp2, for example when implementing non-SOAP REST services, then you must define the following <code>soap_serve()</code> dummy function in your REST service application's source code, see further below. The <code>soap_serve()</code> function is invoked by <code>mod_gsoap</code> for any HTTP POST request received, to handle SOAP/XML and REST HTTP POST service operations.</p>
<p>To support HTTP PUT, PATCH, DELETE and any POST requests, add the corresponding entries to the table:</p>
<div class="fragment"><div class="line"><span class="keyword">static</span> <span class="keyword">struct </span>http_post_handlers handlers[] = {</div><div class="line">  { <span class="stringliteral">&quot;POST&quot;</span>,      generic_POST_handler }, <span class="comment">// warning: overrides soap_serve()</span></div><div class="line">  { <span class="stringliteral">&quot;PUT&quot;</span>,       generic_PUT_handler },</div><div class="line">  { <span class="stringliteral">&quot;PATCH&quot;</span>,     generic_PATCH_handler },</div><div class="line">  { <span class="stringliteral">&quot;DELETE&quot;</span>,    generic_DELETE_handler },</div><div class="line">  { NULL }</div><div class="line">};</div></div><!-- fragment --><p>The httpget plugin sets the <code>soap::fget</code> callback function to serve HTTP GET requests (this disables the <code>?wsdl</code> feature, but which can be implemented by the handler). The httppost plugin sets the <code>soap::fput</code>, <code>soap::fpatch</code> and <code>soap::fdel</code> callbacks to serve HTTP PUT, PATCH and DELETE requests, respectively. The HTTP POST requests are handled differently, via <code>soap_serve()</code> (generated by soapcpp2 if one or more SOAP/XML service operations are defined) that invokes the <code>soap::fform</code> callback that points to the handler. This callback is set by the httppost plugin upon receiving a HTTP POST request that matches the key in the table, i.e. <code>"POST"</code> always matches and <code>"application/json"</code> only matches when the HTTP Content-Type is <code>application/json</code>.</p>
<dl class="section warning"><dt>Warning</dt><dd>a <code>generic_POST_handler</code>, when specified with a <code>"POST"</code> key entry in the table, takes priority over <code>soap_serve()</code>. This means that SOAP/XML messages will not be processed by <code>soap_serve()</code>! Instead, a SOAP/XML handler can be registered with the entries <code>"text/xml"</code> for SOAP 1.1 and <code>"application/soap+xml"</code> for SOAP 1.2 (for SOAP with attachments, also register a <code>"application/xop+xml"</code> handler for MTOM). This handler should invoke <code>soap_serve_request()</code> but never invoke <code>soap_serve()</code>.</dd></dl>
<p>For more details on plugins, see the logging, httpget and httppost plugin documentation in the gSOAP manual.</p>
<p>The following <code>soap</code> context variables are populated from the HTTP request and are made available to be inspected by the plugin handlers:</p>
<ul>
<li><code>soap::action</code> the SOAPAction string or NULL</li>
<li><code>soap::bearer</code> the Bearer token or NULL</li>
<li><code>soap::endpoint</code> the URL string (<a href="http://hostname/path">http://hostname/path</a>) of the request</li>
<li><code>soap::host</code> the hostname string of this server</li>
<li><code>soap::http_content</code> the Content-Type string or NULL (NULL if no Content-Type header was present such as in HTTP GET requests)</li>
<li><code>soap::ip</code> the IP4 address of the client is a 32 bit integer</li>
<li><code>soap::ip6[]</code> the IP6 address of the client is an array of four integers</li>
<li><code>soap::path</code> the path string of the URL</li>
</ul>
<p>The <code>path</code> and <code>http_content</code> strings are very useful to decide the proper response by a handler for to the type of request sent by the client.</p>
<dl class="section warning"><dt>Warning</dt><dd>never return the contents of a file pointed to by <code>soap::endpoint</code> or <code>soap::path</code>, unless the path of the URL is checked in the code to be valid and blocked if it is not. You must prevent unauthorized access to directories and files by returning 404 (Not Found) if the path is not pointing to a publicly-accessible resource. You must also check for <code>..</code> in the path to block requests from snooping around in higher dirs!</dd></dl>
<p>We can register a HTTP GET handler to display this information in a browser:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &quot;plugin/httpget.h&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="apache__gsoap_8h.html">apache_gsoap.h</a>&quot;</span></div><div class="line"></div><div class="line"><span class="keywordtype">int</span> http_get_handler(<span class="keyword">struct</span> soap *soap)</div><div class="line">{</div><div class="line">  <span class="keyword">const</span> <span class="keywordtype">char</span> *content = soap-&gt;http_content;</div><div class="line">  soap-&gt;http_content = <span class="stringliteral">&quot;text/html&quot;</span>; <span class="comment">// the content-type as specified by ...</span></div><div class="line">  soap_response(soap, SOAP_FILE);   <span class="comment">// .... SOAP_FILE</span></div><div class="line">  soap_send(soap, <span class="stringliteral">&quot;&lt;html&gt;&quot;</span>);</div><div class="line">  soap_send(soap, <span class="stringliteral">&quot;&lt;br&gt;Client IP4 = &quot;</span>);</div><div class="line">  soap_send(soap, soap_unsignedInt2s(soap, soap-&gt;ip));</div><div class="line">  soap_send(soap, <span class="stringliteral">&quot;&lt;br&gt;Client IP6 = &quot;</span>);</div><div class="line">  soap_send(soap, soap_unsignedInt2s(soap, soap-&gt;ip6[0]));</div><div class="line">  soap_send(soap, <span class="stringliteral">&quot;.&quot;</span>);</div><div class="line">  soap_send(soap, soap_unsignedInt2s(soap, soap-&gt;ip6[1]));</div><div class="line">  soap_send(soap, <span class="stringliteral">&quot;.&quot;</span>);</div><div class="line">  soap_send(soap, soap_unsignedInt2s(soap, soap-&gt;ip6[2]));</div><div class="line">  soap_send(soap, <span class="stringliteral">&quot;.&quot;</span>);</div><div class="line">  soap_send(soap, soap_unsignedInt2s(soap, soap-&gt;ip6[3]));</div><div class="line">  soap_send(soap, <span class="stringliteral">&quot;.&quot;</span>);</div><div class="line">  soap_send(soap, <span class="stringliteral">&quot;&lt;br&gt;Endpoint = &quot;</span>);</div><div class="line">  soap_send(soap, soap-&gt;endpoint);</div><div class="line">  soap_send(soap, <span class="stringliteral">&quot;&lt;br&gt;Host = &quot;</span>);</div><div class="line">  soap_send(soap, soap-&gt;host);</div><div class="line">  soap_send(soap, <span class="stringliteral">&quot;&lt;br&gt;Path = &quot;</span>);</div><div class="line">  soap_send(soap, soap-&gt;path);</div><div class="line">  soap_send(soap, <span class="stringliteral">&quot;&lt;br&gt;Content-Type = &quot;</span>);</div><div class="line">  soap_send(soap, content ? content : <span class="stringliteral">&quot;N/A&quot;</span>);</div><div class="line">  soap_send(soap, <span class="stringliteral">&quot;&lt;br&gt;SOAPAction = &quot;</span>);</div><div class="line">  soap_send(soap, soap-&gt;action);</div><div class="line">  soap_send(soap, <span class="stringliteral">&quot;&lt;br&gt;Bearer = &quot;</span>);</div><div class="line">  soap_send(soap, soap-&gt;bearer);</div><div class="line">  soap_send(soap, <span class="stringliteral">&quot;&lt;/html&gt;&quot;</span>);</div><div class="line">  soap_end_send(soap); </div><div class="line">  <span class="keywordflow">return</span> SOAP_OK; </div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span> mod_gsoap_init(<span class="keyword">struct</span> soap *soap, request_rec *r)</div><div class="line">{</div><div class="line">  soap_register_plugin_arg(soap, http_get, http_get_handler);</div><div class="line">}</div><div class="line"><a class="code" href="apache__gsoap_8h.html#aa9f6f697cc5fd4ab9e8692c3a97e4a74">IMPLEMENT_GSOAP_SERVER_INIT</a>(mod_gsoap_init) <span class="comment">/* replaces main() { ... } */</span></div></div><!-- fragment --><p>Opening a browser with the server's URL (<code><a href="http://localhost:9080/soap">http://localhost:9080/soap</a></code> for example, as specified in <code>httpd.conf</code>) shows the values associated with the HTTP GET request.</p>
<p>If <code>soap_serve()</code> is not generated by soappcp2, for example when implementing non-SOAP REST services, then you must define the following <code>soap_serve()</code> dummy function in your REST service application's source code:</p>
<div class="fragment"><div class="line"><span class="keywordtype">int</span> soap_serve(<span class="keyword">struct</span> soap *soap)</div><div class="line">{</div><div class="line">  <span class="keywordflow">if</span> (soap_begin_serve(soap) == SOAP_OK)</div><div class="line">    soap-&gt;error = SOAP_NO_METHOD; <span class="comment">// OK, but we have nothing to do</span></div><div class="line">  <span class="keywordflow">return</span> soap-&gt;error</div><div class="line">}</div></div><!-- fragment --><p>The <code>soap_serve()</code> function is invoked by <code>mod_gsoap</code> for any HTTP POST request received, to handle SOAP/XML and REST service operations. In this case we only have REST service operations and there is no <code>soap_serve()</code> generated by soapcpp2 for a SOAP/XML interface header file (e.g. produced by wsdl2h).</p>
<p>The httppost plugin's POST handlers are invoked when <code>soap_begin_serve()</code> executes, before any SOAP/XML request can be handled. If a HTTP plugin is registered to handle POST requests and the POST request was handled successfully, then <code>soap_begin_serve()</code> returns <code>SOAP_STOP</code> indicating that the request was served.</p>
<p>On the other hand, when a request is received that is a valid SOAP/XML POST request (or a POST request that is not handled by one of your registered (generic) POST handlers), then we return <code>SOAP_NO_METHOD</code> or we could return 404 for "Not Found" for example.</p>
<dl class="section warning"><dt>Warning</dt><dd>when implementing SOAP/XML services in addition to REST services, never call <code>soap_serve()</code> in a plugin handler function. The <code>soap_serve()</code> function is already called by the <code>mod_gsoap</code> module. If you want to process a SOAP/XML request in a handler, then call <code>soap_serve_request()</code> to process the XML request message and produce an XML response message for "two-way" SOAP/XML messaging with POST or PATCH. "Two-way" POST or PATCH and "one-way" SOAP/XML messaging with PUT and GET is possible and automatic when the interface header file for soapcpp2 declares protocols for XML REST for service operations <code>ns__Method</code>:</dd></dl>
<div class="fragment"><div class="line"><span class="comment">//gsoap ns service method-protocol: Method1 POST</span></div><div class="line"><span class="keywordtype">int</span> ns__Method1(...);</div><div class="line"><span class="comment">//gsoap ns service method-protocol: Method2 PUT</span></div><div class="line"><span class="keywordtype">int</span> ns__Method2(...);</div><div class="line"><span class="comment">//gsoap ns service method-protocol: Method3 GET</span></div><div class="line"><span class="keywordtype">int</span> ns__Method3(...);</div></div><!-- fragment --><p>The <code>POST</code> (or <code>HTTP</code> which is the same as <code>POST</code>) and <code>PATCH</code> methods are "two-way". The <code>PUT</code> and <code>GET</code> methods are "one-way" REST operations. SOAP protocols for messages with SOAP envelopes are declared similarly:</p>
<div class="fragment"><div class="line"><span class="comment">//gsoap ns service method-protocol: Method1 SOAP</span></div><div class="line"><span class="keywordtype">int</span> ns__Method1(...);</div><div class="line"><span class="comment">//gsoap ns service method-protocol: Method2 SOAP-PUT</span></div><div class="line"><span class="keywordtype">int</span> ns__Method2(...);</div><div class="line"><span class="comment">//gsoap ns service method-protocol: Method3 SOAP-GET</span></div><div class="line"><span class="keywordtype">int</span> ns__Method3(...);</div></div><!-- fragment --><p>The <code>SOAP</code> method is "two-way" messaging with SOAP envelopes. The <code>SOAP-PUT</code> and <code>SOAP-GET</code> methods are "one-way" SOAP operations.</p>
<h1><a class="anchor" id="libraries"></a>
Dynamic libraries                                                   </h1>
<p>If you are using dynamic libraries to deploy services with <code>mod_gsoap</code>, then those should be closed properly to avoid memory leaks. To do so add the following line:</p>
<div class="fragment"><div class="line">dlclose(pConfig-&gt;m_pLibraries-&gt;m_pSOAPLibrary-&gt;m_hLibrary);</div></div><!-- fragment --><p>at the end of the <code><a class="el" href="mod__gsoap_8c.html#a169e2de583e9017593f873dcf1f2173b">gsoap_handler()</a></code> function in <code><a class="el" href="mod__gsoap_8c.html">mod_gsoap.c</a></code>.</p>
<h1><a class="anchor" id="classes"></a>
Building C++ services from service classes                            </h1>
<p>The Apache server is written in C. Building Apache modules in C++ can be tricky and may not be fully guaranteed due to compiler differences. Several online resources exist that offer advice on how to implement C++ modules for Apache 2.x. If this fails, the best alternative is to use FastCGI (see gSOAP user guide on "FastCGI Support").</p>
<p>When using C++ gSOAP service classes generated by <code>soapcpp2</code> options <code>-i</code> or <code>-j</code> we need to implement the C function <code>soap_serve()</code> that dispatches these C++ services.</p>
<p>We will walk you through the implementation of a service using the same calculator example demonstrated above, but written in C++ using a service class <code>calcService</code>.</p>
<p>First, run <code>soapcpp2</code> with option <code>-j</code> to generate a service class: </p><pre class="fragment">soapcpp2 -j -SL -wx calc.h
</pre><p>Create a new <code>calcerver.cpp</code> file with the following code:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &quot;soapcalcService.h&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;calc.nsmap&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="apache__gsoap_8h.html">apache_gsoap.h</a>&quot;</span></div><div class="line"><a class="code" href="apache__gsoap_8h.html#a044247a029c4997b5b22bba46d3ef233">IMPLEMENT_GSOAP_SERVER</a>()</div><div class="line">extern &quot;C&quot; <span class="keywordtype">int</span> soap_serve(struct soap *soap)</div><div class="line">{</div><div class="line">  calcService service(soap);</div><div class="line">  <span class="keywordtype">int</span> err = service.serve();</div><div class="line">  service.destroy();</div><div class="line">  <span class="keywordflow">return</span> err;</div><div class="line">}</div><div class="line"><span class="keywordtype">int</span> calcService::add(<span class="keywordtype">double</span> a, <span class="keywordtype">double</span> b, <span class="keywordtype">double</span> *result)</div><div class="line">{</div><div class="line">  *result = a + b;</div><div class="line">  <span class="keywordflow">return</span> SOAP_OK;</div><div class="line">} </div><div class="line"><span class="keywordtype">int</span> calcService::sub(<span class="keywordtype">double</span> a, <span class="keywordtype">double</span> b, <span class="keywordtype">double</span> *result)</div><div class="line">{</div><div class="line">  *result = a - b;</div><div class="line">  <span class="keywordflow">return</span> SOAP_OK;</div><div class="line">} </div><div class="line"><span class="keywordtype">int</span> calcService::mul(<span class="keywordtype">double</span> a, <span class="keywordtype">double</span> b, <span class="keywordtype">double</span> *result)</div><div class="line">{</div><div class="line">  *result = a * b;</div><div class="line">  <span class="keywordflow">return</span> SOAP_OK;</div><div class="line">} </div><div class="line"><span class="keywordtype">int</span> calcService::div(<span class="keywordtype">double</span> a, <span class="keywordtype">double</span> b, <span class="keywordtype">double</span> *result)</div><div class="line">{</div><div class="line">  *result = b != 0 ? a / b : 0.0;</div><div class="line">  <span class="keywordflow">return</span> SOAP_OK;</div><div class="line">} </div><div class="line"><span class="keywordtype">int</span> calcService::pow(<span class="keywordtype">double</span> a, <span class="keywordtype">double</span> b, <span class="keywordtype">double</span> *result)</div><div class="line">{</div><div class="line">  *result = ::pow(a, b);</div><div class="line">  <span class="keywordflow">return</span> SOAP_OK;</div><div class="line">}</div></div><!-- fragment --><p>Here, <code>calcService</code> is the service class declared and defined in the generated <code>soapcalcService.h</code> and <code>soapcalcService.cpp</code> files, respectively.</p>
<p>The <code>apxs</code> command is used to compile as follows, with the <code>-S CC=c++</code> option: </p><pre class="fragment">bin/apxs -a -c -S CC=c++ calcserver.cpp soapC.cpp soapcalcService.cpp stdsoap2.cpp
chmod 755 .lib/calcserver.so
</pre><p>This creates <code>.libs/calcserver.so</code> service module that is universally readable. Also make sure that <code>.libs/calcserver.so</code> is readable through the entire path, that is through <code>/home/username/apachegsoap/.libs</code>.</p>
<p>After compilation, the new module should be added to <code>httpd.conf</code> as was explained above.</p>
<p>When multiple service classes are defined, when <code>soapcpp2 -j</code> is applied to multiple <code>.h</code> files, then you have two options:</p>
<ol type="1">
<li>create an <code>.so</code> library for each service with the <code>apxs</code> command and add each module to <code>httpd.conf</code> with a new <code>Location</code> property.</li>
<li>create one <code>.so</code> library with the services combined, all listening to the same service URL. Only one module is added to <code>httpd.conf</code> since the <code>Location</code> property is the same. Note that the <code>?wsdl</code> query is not as useful in this case, since we cannot publicize the service WSDLs combined.</li>
</ol>
<p>The second option requires C++ namespaces as explained in section "How to Chain
C++ Server Classes to Accept Messages on the Same Port" in the gSOAP user guide. Basically, you should chain the services as follows:</p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="apache__gsoap_8h.html">apache_gsoap.h</a>&quot;</span></div><div class="line"><a class="code" href="apache__gsoap_8h.html#a044247a029c4997b5b22bba46d3ef233">IMPLEMENT_GSOAP_SERVER</a>()</div><div class="line">extern &quot;C&quot; <span class="keywordtype">int</span> soap_serve(struct soap *soap)</div><div class="line">{</div><div class="line">  <span class="keywordtype">int</span> err;</div><div class="line">  <span class="keywordflow">if</span> ((err = soap_begin_serve(soap)) == SOAP_OK)</div><div class="line">  {</div><div class="line">    X::Service service_x(soap);</div><div class="line">    <span class="keywordflow">if</span> ((err = service_x.dispatch()) == SOAP_NO_METHOD)</div><div class="line">    {</div><div class="line">      Y::Service service_y(soap);</div><div class="line">      <span class="keywordflow">if</span> ((err = service_y.dispatch()) == SOAP_NO_METHOD)</div><div class="line">      {</div><div class="line">        Z::Service service_z(soap);</div><div class="line">        err = service_z.dispatch();</div><div class="line">      }</div><div class="line">    }</div><div class="line">  }               </div><div class="line">  soap_destroy(soap);</div><div class="line">  soap_end(soap);</div><div class="line">  <span class="keywordflow">return</span> err;</div><div class="line">}</div></div><!-- fragment --><h1><a class="anchor" id="debug"></a>
Troubleshooting                                                         </h1>
<p>It is recommended to test the service first as a stand-alone server over a port using <code>soap_bind()</code> and <code>soap_accept()</code>. Debugging is much easier this way.</p>
<p>After testing as a stand-alone server, to debug the service with the Apache module, compile your service application with compiler option <code>-g</code> (apxs option <code>-Wc,-g</code>to control debug information output. For example: </p><pre class="fragment">bin/apxs -Wc,-g -a -c calcserver.c soapC.c soapServer.c stdsoap2.c
</pre><p>Debug the service as it is deployed while <code>httpd</code> is running. To do so, we first stop the service and start it up in single threaded mode so we can attach to it to a debugger such as <code>gdb</code> or <code>lldb</code>: </p><pre class="fragment">cd apachegsoap
bin/apachectl stop
bin/httpd -X -f /home/username/apachegsoap/conf/httpd.conf &amp;
</pre><p>You will get a process ID, say 12345, which we will attach to a debugger: </p><pre class="fragment">gdb -p 12345
</pre><p>You will see a load of symbols loading, including <code>mod_gsoap.so</code>.</p>
<p>Next, we set a breakpoint on the <code>soap_serve</code> call (the main entry point), let <code>gdb</code> know that we accept the pending breakpoint, and then continue the process: </p><pre class="fragment">(gdb) b soap_serve
Function "soap_serve" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (soap_serve) pending.
(gdb) c
Continuing.
</pre><p>We execute our <code>calcclient</code> from another window, which triggers the breakpoint. </p><pre class="fragment">[Switching to Thread 0x7f3fbd209950 (LWP 25493)]
Breakpoint 1, 0x00007f3fb059e398 in soap_serve () from /home/username/apachegsoap/gsoap-2.8/gsoap/samples/calc/.libs/calcserver.so
Current language: auto; currently asm
(gdb) n
Single stepping until exit from function soap_serve,
which has no line number information.
0x00007f3fb05a5eec in apache_default_soap_serve () from /home/username/apachegsoap/gsoap-2.8/gsoap/samples/calc/.libs/calcserver.so
(gdb)
</pre><p>Note that when Apache <code>httpd</code> runs as user <code>wwwrun</code> (or another user) then you will have to run the debugger as that same user. To do so, execute: </p><pre class="fragment">sudo -u wwwrun gdb /usr/sbin/httpd2-worker 25487
</pre><p>When failures occur, see also the error logs that are saved by httpd to <code>/home/username/apachegsoap/logs/error_log</code>.</p>
<p>Thanks to Jon Scobie for suggestions to improve this section.</p>
<h1><a class="anchor" id="limitations"></a>
Limitations                                                       </h1>
<p>The gSOAP Apache module does not support receiving DIME protocol messages with attachments. MIME and MTOM attachments are supported.</p>
<h1><a class="anchor" id="license"></a>
License                                                               </h1>
<p>The Apache modules for gSOAP are released under the gSOAP open source public license and GPLv2. The open source licensing is replaced by Genivia's license for commercial use when a commercial-use license is purchased by customer.</p>
<h1><a class="anchor" id="references"></a>
Further reading                                                    </h1>
<p><a href="http://techiebitsandpieces.blogspot.com/2011/03/all-things-modgsoap.html">All things <code>mod_gsoap</code></a> by Jon Scobie</p>
<p><a href="http://httpd.apache.org/download.cgi">Apache HTTP server project</a>. </p>
</div></div><!-- contents -->
<hr class="footer">
<address class="footer">
Copyright (C) 2021, Robert van Engelen, Genivia Inc., All Rights Reserved.
</address>
<address class="footer"><small>
Converted on Thu Jun 24 2021 18:08:28 by <a target="_blank" href="http://www.doxygen.org/index.html">Doxygen</a> 1.8.11</small></address>
<br>
<div style="height: 246px; background: #DBDBDB;">
</body>
</html>
